﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections;


namespace Devtm.ServiceModel.Discovery.Collection
{
    public static class HelperTable
    {


    
        [System.Diagnostics.DebuggerStepThrough]
        public static void ApplyChange<T>(this System.Collections.Specialized.NotifyCollectionChangedEventArgs e, Action<T> addAction = null, Action<T> delAction = null, Action resetAction = null)
        //where T : class
        {

            switch (e.Action)
            {


                case NotifyCollectionChangedAction.Add:
                    if (addAction != null)
                        foreach (var item in e.NewItems)
                        {

                            if (item is T)
                                addAction((T)item);

                            else
                            {
                                var lst = item as IEnumerable<T>;
                                if (lst != null)
                                    foreach (T item3 in lst)
                                        if (item3 is T)
                                            addAction(item3);
                            }
                        }
                    break;


                case NotifyCollectionChangedAction.Remove:
                    if (delAction != null)
                        foreach (var item2 in e.OldItems)
                        {
                            if (item2 is T)
                                delAction((T)item2);

                            else
                            {
                                var lst = item2 as IEnumerable<T>;
                                if (lst != null)
                                    foreach (T item3 in lst)
                                        if (item3 is T)
                                            delAction(item3);
                            }
                        }
                    break;


                case NotifyCollectionChangedAction.Reset:
                    if (resetAction != null)
                        resetAction();


                    break;



                case NotifyCollectionChangedAction.Move:
                case NotifyCollectionChangedAction.Replace:
                default:
                    break;
            }


        }





        public static T Detach<T, TKey>(this TableCollection<T, TKey> source, TKey key)
        {
            T item = source[key];
            source.Remove(source[key]);
            return item;
        }


        /// <summary>
        /// Clones this instance.
        /// </summary>
        /// <returns></returns>
        public static TableCollection<T, TKey> Clone<T, TKey>(this TableCollection<T, TKey> source)
        {
            if (source.ObjectIsKey)
                return new TableCollection<T, TKey>((Hashtable)source._Lst.Clone());
            else
                return new TableCollection<T, TKey>(source.FieldExpression, (Hashtable)source._Lst.Clone());
        }


        /// <summary>
        /// Copies the values in array from index.
        /// the array must be (array.Length - indexarray) < TableCollection.Count
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="indexarray">The indexarray.</param>
        public static void CopyTo<T, TKey>(this TableCollection<T, TKey> source, T[] array, int indexarray)
        {

            if (array == null)
                throw new ArgumentNullException("array", "Argument Array is null");

            if (array.Rank != 1)
                throw new ArgumentException("Arg_RankMultiDimNotSupported");

            if (indexarray < 0)
                throw new ArgumentOutOfRangeException("Argument Out Of Range");

            if ((array.Length - indexarray) < source._Lst.Count)
                throw new ArgumentException("Array Too Small");

            source.CopyValues(array, indexarray);

        }


        public static IEnumerable<T> NotInList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<T> items)
        {

            Hashtable tb = new Hashtable();
            foreach (T i in items)
                if (!tb.ContainsKey(i))
                    tb.Add(source.GetKey(i), i);

            foreach (T item in source)
                if (!tb.ContainsValue(item))
                    yield return item;

        }
        public static IEnumerable<TKey> NotInList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<TKey> keys)
        {

            Hashtable tb = new Hashtable();
            foreach (TKey i in keys)
                if (!tb.ContainsKey(i))
                    tb.Add(i, i);

            foreach (T item in source)
                if (!tb.ContainsKey(item))
                    yield return source.GetKey(item);

        }


        public static void RemoveList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<TKey> keys)
        {
            var lst = keys.ToList();
            foreach (TKey key in lst)
                if (source.ContainsKey(key))
                    source.RemoveKey(key);
        }
        public static void RemoveList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<T> items)
        {
            var lst = items.ToList();
            foreach (T item in lst)
                if (source.Contains(item))
                    source.Remove(item);
        }


        public static void RemoveNotInList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<T> items)
        {
            List<T> i = source.NotInList(items).ToList();
            source.RemoveList(i);
        }
        public static void RemoveNotInList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<TKey> keys)
        {
            List<TKey> i = source.NotInList(keys).ToList();
            source.RemoveList(i);
        }


        public static void RefreshList<T, TKey>(this ITableCollection<T, TKey> source, IEnumerable<T> items)
        {

            var lst = items.ToList();

            foreach (T item in lst)
                if (!source.Contains(item))
                    source.Add(item);

            source.RemoveNotInList(lst);

        }



        public static IEnumerable<T> GetList<T>(this IEnumerable source)
        {
            foreach (T item in source)
                yield return item;
        }



        /// <summary>
        /// Adds the list's element.
        /// </summary>
        /// <param name="items">The items.</param>
        public static void AddRange<T, TKey>(this ITableCollection<T, TKey> source, params T[] items)
        {
            source.AddList(items.ToList());
        }


    }
}
